#include "ast.hpp"
#include "lexer.hpp"

ListNode::ListNode() {
    _node_list = new vector<Node*>();
}

void ListNode::add(Node* n) {
    _node_list->push_back(n);
}

void Node::dump() {
    
}

VarNode::VarNode(Token* t) {
    _name = new char[t->_length + 1];
    _name[t->_length] = '\0';
    strncpy(_name, t->_value, t->_length);
}

/**
 * Dump functions for all nodes.
 */
void AssignNode::dump() {
    printf("(= ");
    _left->dump();
    printf(" ");
    _right->dump();
    printf(")\n");
}

void VarNode::dump() {
    printf("%s", _name);
}

void CmpNode::dump() {
    if (_cmp_op == CMP_LT) {
        printf("(< ");
    }
    _left->dump();
    printf(" ");
    _right->dump();
    printf(")");
}

void ConstInt::dump() {
    printf("%d", _value);
}

void PrintNode::dump() {
    printf("print(");
    _value->dump();
    printf(")\n");
}

void IfNode::dump() {
    printf("if(");
    _cond->dump();
    printf(") then ");
    _then->dump();

    if (_else != NULL) {
        printf(" else ");
        _else->dump();
    }
}

void ListNode::dump() {
    printf("[");
    for (auto it = _node_list->begin(); it != _node_list->end(); it++) {
        (*it)->dump();
        printf(", ");
    }
    printf("]\n");
}

void BinaryOp::dump() {
    switch(_op_type) {
    case AST_OP_ADD:
        printf("(+ ");
        break;
    case AST_OP_SUB:
        printf("(- ");
        break;
    case AST_OP_MUL:
        printf("(* ");
        break;
    case AST_OP_DIV:
        printf("(/ ");
        break;
    case AST_OP_BIT_AND:
	    printf("(& ");
        break;
    case AST_OP_BIT_OR:
	    printf("(| ");
        break;
    case AST_OP_BIT_XOR:
	    printf("(^ ");
        break;
    case AST_OP_LOG_OR:
	    printf("(or ");
        break;
    case AST_OP_LOG_AND:
	    printf("(and ");
        break;
    case AST_OP_LEFT_SHIFT:
	    printf("(<< ");
        break;
    case AST_OP_RIGHT_SHIFT:
	    printf("(>> ");
        break;
    default:
        printf("Unknown binary op %d\n", _op_type);
        return;
    }

    _left->dump();
    printf(" ");
    _right->dump();
    printf(")");
}

void BinaryOp::set_left(Node* left) {
    _left = left;
}

void BinaryOp::set_right(Node* right) {
    _right = right;
}

void LogicNotNode::dump() {
    printf("(~ ");
    _value->dump();
    printf(")");
}

